package project1;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

//判断五子棋获胜的方法
//isWinner检查黑棋有没有获胜，再检查白棋有没有获胜
//获胜->isGameover=true
//isWinner内部利用CheckDirection检查x,y,对角线和反对角线上是否有5个棋子在一条线上
//CheckDirection内部对于每一个棋子，判断是否有一个方向满足5个棋子在一条线上，利用isSameColor判断某个方向上棋子是否是一个颜色

/**五子棋核心逻辑
 * <p>棋盘绘制、下棋逻辑、判断是否获胜、悔棋功能</p>
 *
 * @see project1.Register 注册界面
 * @see project1.Login 登录界面
 * @see project1.Gomoku 主界面入口
 * @see project1.SaveGomoku 保存游戏界面
 *
 */
@Gomoku_Component("棋盘绘制")
public class DrawGomoku extends JPanel {
    /* 黑棋/白棋坐标存储列表
     * <p>坐标原点位于棋盘左上角，每个格子20x20像素</p>
     * <p>每个点的坐标为(x,y)，其中x为列数，y为行数</p>
     */
    java.util.List<Point> Black_chess = new ArrayList<Point>();//ArrayList动态数组
    List<Point> White_chess = new ArrayList<>();;

    List<Point> Player_chess = new ArrayList<>();//玩家下棋坐标存储列表-->黑棋
    List<Point> AI_chess = new ArrayList<>();//AI下棋坐标存储列表-->白棋
    Boolean isBlackChess = true;
    Boolean isGameOver = false;//判断比赛是否结束
    int Mode = 1;
    //Mode=1为玩家对玩家模式，Mode=2为玩家对AI模式

    @Gomoku_Event(event = "鼠标点击下棋")
    MouseAdapter mouseAdapter1 = new MouseAdapter() {
        @Gomoku_Event(event = "判断是否有人获胜")
        @Override
        public void mouseClicked(MouseEvent e) {
            for(Point p : Black_chess) {
                if(isWinner(p,Black_chess)){
                    System.out.println("黑棋获胜");
                    isGameOver = true;
                    break;
                }
            }
            for(Point p : White_chess) {
                if(isWinner(p,White_chess)){
                    System.out.println("白棋获胜");
                    isGameOver = true;
                    break;
                }
            }
            //黑棋会覆盖白棋，白棋会覆盖黑棋
           if(!isPointused(new Point(e.getX(), e.getY()),Black_chess,White_chess) && isPointInArea(new Point(e.getX(), e.getY()))&&!isGameOver){
                if (isBlackChess)
                    Black_chess.add(new Point(e.getX(), e.getY()));
                else
                    White_chess.add(new Point(e.getX(), e.getY()));

                isBlackChess = !isBlackChess;
                repaint();
            }

        }
    };


    MouseAdapter mouseAdapter2 = new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            for (Point p : Player_chess) {
                if (isWinner(p, Player_chess)) {
                    System.out.println("玩家获胜");
                    isGameOver = true;
                    break;
                }
            }

            for (Point p : AI_chess) {
                if (isWinner(p, AI_chess)) {
                    System.out.println("AI获胜");
                    isGameOver = true;
                    break;
                }
            }
            //之前Player_chess和AI_chess填成了Black_chess和White_chess，导致错误
            if (isPointInArea(new Point(e.getX(), e.getY())) && !isPointused(new Point(e.getX(), e.getY()), Player_chess, AI_chess) && !isGameOver) {
                if (isBlackChess) {
                    Player_chess.add(new Point(e.getX(), e.getY()));
                    repaint();
                    if (isWinner(new Point(e.getX(), e.getY()), Player_chess)) {
                        System.out.println("玩家获胜");
                        isGameOver = true;
                        return;
                    }

                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                Thread.sleep(500);// 延迟500ms
                                if (!isGameOver) { // 确保游戏没有结束
                                    GomokuAI G_AI = new GomokuAI(DrawGomoku.this);
                                    G_AI.move();
                                    repaint(); // AI落子后重绘

                                    // 检查AI是否获胜
                                    if (!AI_chess.isEmpty()) {
                                        Point lastAIMove = AI_chess.get(AI_chess.size() - 1);
                                        if (isWinner(lastAIMove, AI_chess)) {
                                            System.out.println("AI获胜");
                                            isGameOver = true;
                                        }
                                    }
                                }
                            } catch (InterruptedException e1) {
                                e1.printStackTrace();
                            }
                        }
                    });
                }
                isBlackChess = !isBlackChess;
            }
        }
    };


    @Gomoku_Event(event = "判断点是否在区域内部")
    Boolean isPointInArea(Point p){
        if(p.x<100||p.x>400||p.y<100||p.y>400)
            return false;
        return true;
    };

    @Gomoku_Event(event = "判断点是否被使用")
    Boolean isPointused(Point p, List<Point> points1, List<Point> points2){
        @Gomoku_Event(event = "把点定位到坐标")
        //把p.x转换到具体哪一个格子
        int x = (p.x-100)/20+1;
        int y = (p.y-100)/20+1;
        for(Point P: points1){
            //把P.x转换到具体哪一个格子
            int Px = (P.x-100)/20+1;
            int Py = (P.y-100)/20+1;
            //判断是否在一个方格内
            if(x==Px && y==Py)
                return true;
        }
        for(Point P: points2){
            int Px = (P.x-100)/20+1;
            int Py = (P.y-100)/20+1;
            if(x==Px&& y==Py)
                return true;
        }
        return false;
    };

    @Gomoku_Event(event = "判断是否有人获胜->检查是否有5个棋子在一条线上")
    private Boolean isWinner(Point p, List<Point>points){
        int x = (p.x-100)/20+1;
        int y = (p.y-100)/20+1;
        //判断是否有5个棋子在一条线上
        if(CheckDirection(x,y,-1,0,points)||CheckDirection(x,y,1,0,points)||CheckDirection(x,y,0,-1,points)||CheckDirection(x,y,0,1,points)
        ||CheckDirection(x,y,-1,-1,points)||CheckDirection(x,y,1,1,points)||CheckDirection(x,y,1,-1,points)||CheckDirection(x,y,-1,1,points))
            return true;
        return false;
    }
    @Gomoku_Event(event = "检查是否有5个棋子在一条线上")
    private Boolean CheckDirection(int x,int y, int dx, int dy,List<Point>points){
        int count = 1;
        for(int i=1;i<5;i++){
            if(!isSameColor(x+i*dx,y+i*dy,points))
                break;
            count++;
        }
        return count>=5;
    };

    @Gomoku_Event(event = "判断某个方向上棋子是否是一个颜色")
    Boolean isSameColor(int x, int y, List<Point> points){
        for(Point P: points){
            //网格坐标
            int Px = (P.x-100)/20+1;
            int Py = (P.y-100)/20+1;
            if(Px==x && Py==y)
                return true;
        }
        return false;
    }


        @Override
        public void paint (Graphics g){
            super.paint(g);
            g.clearRect(100, 100, 300, 300);
            g.setColor(Color.GRAY);
            g.fillRect(100, 100, 300, 300);

            g.setColor(Color.BLACK);
            g.drawLine(100, 100, 400, 100);
            g.drawLine(100, 100, 100, 400);
            g.drawLine(400, 100, 400, 400);
            g.drawLine(100, 400, 400, 400);

            g.drawLine(100, 120, 400, 120);
            g.drawLine(100, 140, 400, 140);
            g.drawLine(100, 160, 400, 160);
            g.drawLine(100, 180, 400, 180);
            g.drawLine(100, 200, 400, 200);
            g.drawLine(100, 220, 400, 220);
            g.drawLine(100, 240, 400, 240);
            g.drawLine(100, 260, 400, 260);
            g.drawLine(100, 280, 400, 280);
            g.drawLine(100, 300, 400, 300);
            g.drawLine(100, 320, 400, 320);
            g.drawLine(100, 340, 400, 340);
            g.drawLine(100, 360, 400, 360);
            g.drawLine(100, 380, 400, 380);
            g.drawLine(100, 400, 400, 400);
            g.drawLine(120, 100, 120, 400);
            g.drawLine(140, 100, 140, 400);
            g.drawLine(160, 100, 160, 400);
            g.drawLine(180, 100, 180, 400);
            g.drawLine(200, 100, 200, 400);
            g.drawLine(220, 100, 220, 400);
            g.drawLine(240, 100, 240, 400);
            g.drawLine(260, 100, 260, 400);
            g.drawLine(280, 100, 280, 400);
            g.drawLine(300, 100, 300, 400);
            g.drawLine(320, 100, 320, 400);
            g.drawLine(340, 100, 340, 400);
            g.drawLine(360, 100, 360, 400);
            g.drawLine(380, 100, 380, 400);
            g.drawLine(400, 100, 400, 400);

            if(Mode==1)
                normal_mode(g);
            if(Mode==2)
                AI_mode(g);
        }

        public void normal_mode(Graphics g){
            for (Point p : Black_chess) {
//            if(!isPointused(p))
//                continue;  错误一个白棋用掉后就变成黑棋
                g.setColor(Color.BLACK);
                //棋盘坐标
                int x = (p.x - 100) / 20;
                int y = (p.y - 100) / 20;
                p.x = x * 20 + 105;
                p.y = y * 20 + 105;
                g.fillOval(p.x, p.y, 10, 10);
            }
            for (Point p : White_chess) {
//            if(!isPointused(p))
//                continue;
                g.setColor(Color.WHITE);
                int x = (p.x - 100) / 20;
                int y = (p.y - 100) / 20;
                p.x = x * 20 + 105;
                p.y = y * 20 + 105;
                g.fillOval(p.x, p.y, 10, 10);
                g.setColor(Color.BLACK);
                g.drawOval(p.x, p.y, 10, 10);
            }
        }


        public void AI_mode(Graphics g){
            for (Point p : Player_chess) {
                g.setColor(Color.BLACK);
                int x = (p.x - 100) / 20;
                int y = (p.y - 100) / 20;
                p.x = x * 20 + 105;
                p.y = y * 20 + 105;
                g.fillOval(p.x, p.y, 10, 10);
            }

            for (Point p : AI_chess) {
                g.setColor(Color.WHITE);
                g.fillOval(p.x, p.y, 10, 10);
                g.setColor(Color.BLACK);
                g.drawOval(p.x, p.y, 10, 10);
            }
        }

        //将网格坐标转换为棋盘坐标
        public int[] grid_board(int x,int y){
            //网格坐标
            //棋盘坐标
            x = (x-1)*20+105;
            y = (y-1)*20+105;
            return new int[]{x,y};
        }

        //将棋盘坐标转换为网格坐标
        public int[] board_grid(Point p){
            //棋盘坐标
            //网格坐标
            int x = (p.x-100)/20+1;
            int y = (p.y-100)/20+1;
            return new int[]{x,y};
        }
    }